package com.tuniu.agents.common.logger;

import com.tuniu.agents.message.MessageLogger;
import com.tuniu.agents.message.MessageSender;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

/**
 * Recommender Aspect
 */
@Aspect
@Component
public class RecommenderAgentLoggerAspect extends LoggerAspect{

    private static final Logger LOGGER = LoggerFactory.getLogger(RecommenderAgentLoggerAspect.class);

    public RecommenderAgentLoggerAspect(ApplicationContext applicationContext, MessageSender messageSender) {
        super(applicationContext, messageSender);
    }

    // Define pointcut: all call and stream methods of classes that inherit from Agent
    @Pointcut("execution(* com.tuniu.agents.*.call(String, String)) || " +
            "execution(* com.tuniu.agents..*.call(String, java.util.List)) || " +
            "execution(* com.tuniu.agents..*.callResponse(String, String)) || " +
            "execution(* com.tuniu.agents..*.callResponse(String, java.util.List)) || " +
            "execution(* com.tuniu.agents..*.stream(String, String)) || " +
            "execution(* com.tuniu.agents..*.stream(String, java.util.List)) || " +
            "execution(* com.tuniu.agents..*.streamResponse(String, String)) || " +
            "execution(* com.tuniu.agents..*.streamResponse(String, java.util.List))")
    public void agentMethods() {}

    /**
     * Define pointcut: all classes that inherit from SelectionAgent/RecommenderAgent, only intercept call and stream methods
     */
    @Pointcut("agentMethods() && (within(com.tuniu.agents.common.agent.Recommender+))")
    public void agentClasses() {}

    @Around("agentClasses()")
    public Object aroundAgentMethod(ProceedingJoinPoint joinPoint) throws Throwable {

        // Get the target object (instance of Recommender)
        Object target = joinPoint.getTarget();

        // Now get the value of a specific field (e.g., 'agentName' field)
        String fieldName = "messageLogger"; // Replace with the field name you need to access
        MessageLogger logger = null;
        try {
            Field field = target.getClass().getSuperclass().getDeclaredField(fieldName);
            field.setAccessible(true); // Set field to be accessible
            logger = (MessageLogger) field.get(target); // Get field value
        } catch (NoSuchFieldException | IllegalAccessException e) {
            // Log error or throw custom exception
            LOGGER.error("Failed to access field: " + fieldName);
        }
        Object result = getResult(joinPoint, logger);

        return result;
    }

    @Override
    public String getConversationId(Object[] args) {
        Object conversationId = args[0];
        return conversationId == null ? null : String.valueOf(conversationId);
    }

}
